//web3.js
import abi from "./abi.json";
const Web3 = require('web3');
const BN = require('bn.js');
export default class WKC {
    // WKC智能合约地址
    contractAddress = '0xf51A26229E0109924458472cC9fDD3D31C50F104';
    // 智能合约ABI
    contractABI = abi;
    contract = null;
    web3 = null;
    theAccount = null;
    /**
     * 初始化
     * @param {Object} callback 返回账户地址
     */
    Init(callback) {
        //判断用户是否安装MetaMask钱包插件
        if (typeof window.ethereum === "undefined") {
            //没安装MetaMask钱包进行弹框提示
            alert("Looks like you need a Dapp browser to get started.");
            alert("Consider installing MetaMask!");
        } else {
            window.web3 = new Web3(window.ethereum);
            this.web3 = window.web3;
            //如果用户安装了MetaMask，你可以要求他们授权应用登录并获取其账号
            window.ethereum.enable()
                .catch(function (reason) {
                    //如果用户拒绝了登录请求
                    if (reason === "User rejected provider access") {
                        // 用户拒绝登录后执行语句；
                    } else {
                        // 本不该执行到这里，但是真到这里了，说明发生了意外
                        alert("There was an issue signing you in.");
                    }
                }).then(accounts => {
                    this.contract = new window.web3.eth.Contract(this.contractABI, this.contractAddress);
                    console.log('地址', accounts)
                    console.log('合约', this.contract)
                    this.theAccount = accounts[0];
                    //这里返回用户钱包地址
                    callback(accounts[0]);
                });
        }
    }
    async totalSupply() {
        let value = await this.contract.methods.totalSupply().call();
        return this.fromWei(value);
    }
    async issue_max() {
        let value = await this.contract.methods.issue_max().call();
        return this.fromWei(value);
    }
    async issue_amount() {
        let value = await this.contract.methods.issue_amount().call();
        return this.fromWei(value);
    }
    async air_drop_max() {
        let value = await this.contract.methods.air_drop_max().call();
        return this.fromWei(value);
    }
    async air_drop_amount() {
        let value = await this.contract.methods.air_drop_amount().call();
        return this.fromWei(value);
    }
    async burning_amount() {
        let value = await this.contract.methods.burning_amount().call();
        return this.fromWei(value);
    }
    async minBalanceForAward() {
        let value = await this.contract.methods.minBalanceForAward().call();
        return this.fromWei(value);
    }
    async taxFeeForAward() {
        let value = await this.contract.methods.taxFeeForAward().call();
        return value;
    }
    async pawnAwardAmountPerBNB() {
        let value = await this.contract.methods.pawnAwardAmountPerBNB().call();
        return this.fromWei(value);
    }
    async minPawnBNBAmount() {
        let value = await this.contract.methods.minPawnBNBAmount().call();
        return this.fromWei(value);
    }
    async contractBNBBalance(){
        let balance = await this.web3.eth.getBalance(this.contractAddress)
        return this.fromWei(balance);
    }
    async award_max(){
        let value = await this.contract.methods.award_max().call();
        return this.fromWei(value);
    }
    async award_max_per_trans(){
        let value = await this.contract.methods.award_max_per_trans().call();
        return this.fromWei(value);
    }
    async award_amount(){
        let value = await this.contract.methods.award_amount().call();
        return this.fromWei(value);
    }

    async balanceOf(address){
        let value = await this.contract.methods.balanceOf(address).call();
        return this.fromWei(value);
    }

    async mint(recipient, valueEthStr){
        var miner = this.normal_addr(this.theAccount);
        recipient = this.normal_addr(recipient);
        var value = this.toWei(valueEthStr);
        let data =  await this.contract.methods.mint(recipient, value).encodeABI();
        return this._sendRawTransaction(miner, this.contractAddress, '0x0', data);
    }

    async pawnBNB(valueEthStr){
        var value = new BN(this.toWei(valueEthStr));
        let data =  await this.contract.methods.pawn().encodeABI();
        return this._sendRawTransaction(this.normal_addr(this.theAccount), this.contractAddress, '0x'+value.toString(16), data);
    }

    async ransomBNBbyWKC(valueEthWKCStr){
        var value = new BN(this.toWei(valueEthWKCStr));
        let data =  await this.contract.methods.ransom(value).encodeABI();
        return this._sendRawTransaction(this.normal_addr(this.theAccount), this.contractAddress, '0x0', data);
    }

    async _sendRawTransaction(from, to, valueHexStr, data = "0x") {
        from = this.normal_addr(from);
        to = this.normal_addr(to);
        const transactionParameters = {
            gas: '0x2710', // customizable by user during MetaMask confirmation.
            gasLimit: '0x295f05',
            to: to, // Required except during contract publications.
            from: from, // must match user's active address.
            value: valueHexStr, // Only required to send ether to the recipient from the initiating external account.
            data:data
          };
          
          // txHash is a hex string
          // As with any RPC call, it may throw an error
          const txHash = await window.ethereum.request({
            method: 'eth_sendTransaction',
            params: [transactionParameters],
          });
          return txHash;
    }

    /**
         * 以太->微
         * @param value 以太
         */
    toWei(value, unit = "ether") {
        return this.web3.utils.toWei(String(value), unit)
    }

    /**
     * 微->以太
     * @param value 微数
     */
    fromWei(value, unit = "ether") {
        return this.web3.utils.fromWei(String(value), unit)
    }

    normal_addr(address){
        if(address.slice(0,2).toLowerCase() == '0x'){
            address = address.slice(2);
            if(address.slice(0,2).toLowerCase() == '0x'){
                address = address.slice(2);
            }
        }
        address = '0x' + address;
        if(address.length != '42'){
            throw new Error(`unknown address:${address}`);
        }
        return address;
    }
}